package com.logica.mdm.webservices.utils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.cxf.common.util.StringUtils;
import com.siperian.sif.message.SiperianRequest;

/**
 * Utility methods for SiperianRequest building.
 * @author Fabien Crespel <fabien.crespel@logica.com>
 */
public class SiperianRequestUtils {

	private static final String MAPPING_MESSAGE_PACKAGE = "com.siperian.sif.message.nexity.mappings";
	private static final String MAPPING_OBJECT_PACKAGE = "com.siperian.sif.dataobject.nexity.mappings";
	
	private static final Map<String, Class<?>> classMap = new HashMap<String, Class<?>>();

	/**
	 * Lookup a class from a local cache, and load it as needed.
	 * @param className name of the class to lookup
	 * @return Class object
	 * @throws ClassNotFoundException
	 */
	protected static Class<?> lookupClass(String className) throws ClassNotFoundException {
		Class<?> clazz = classMap.get(className);
		if (clazz == null) {
			clazz = Class.forName(className);
			classMap.put(className, clazz);
		}
		return clazz;
	}
	
	/**
	 * Build a strongly typed CleansePutRequest dynamically.
	 * @param requestType the request type, as seen in the ORS-specific API class name (e.g. CrmContact for CleansePutCrmContactRequest)
	 * @param requestTemplate an object whose properties will be copied to the CleansePutRequest
	 * @param dataObject an arbitrary data object whose properties will be used as the CleansePut mapping input
	 * @return an instantiated, strongly typed CleansePutRequest object
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 */
	@SuppressWarnings("unchecked")
	public static SiperianRequest buildCleansePutRequest(String requestType, Object requestTemplate, Object dataObject) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		Class<? extends SiperianRequest> requestClass = (Class<? extends SiperianRequest>) lookupClass(MAPPING_MESSAGE_PACKAGE + ".CleansePut" + requestType + "Request");
		Class<?> dataObjectClass = lookupClass(MAPPING_OBJECT_PACKAGE + "." + requestType + "Input");

		Object requestData = dataObjectClass.newInstance();
		PropertyUtils.copyProperties(requestData, dataObject);
		
		SiperianRequest request = requestClass.newInstance();
		PropertyUtils.copyProperties(request, requestTemplate);
		PropertyUtils.setSimpleProperty(request, StringUtils.uncapitalize(requestType) + "Input", requestData);
		
		return request;
	}
}
